/*
 * Copyright 2010 Pierre Heinzerling, Uwe Janner, Patrick Wright
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * 
 */
package com.upp.web;

import java.io.IOException;
import java.util.logging.Logger;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.upp.publinksky.model.UserStatus;
import com.upp.publinksky.operations.authentication.LoginStatus;

/**
 * a filter that lets nobody in that is not authorized by google;
 * @author uwe janner
 *
 */
public class AssureAuthorizationFilter implements Filter {
    private static final Logger log = Logger.getLogger(AssureAuthorizationFilter.class.getName());
    
    private static ThreadLocal<RequestContext> requestContexts = new ThreadLocal<RequestContext>();

	public AssureAuthorizationFilter() {
	}

	/* (non-Javadoc)
	 * @see javax.servlet.Filter#destroy()
	 */
	@Override
	public void destroy() {
	}

	/* (non-Javadoc)
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	@Override
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();

		HttpServletRequest httpServletRequest = (HttpServletRequest)req;
		String requestURI = httpServletRequest.getRequestURI();
		HttpServletResponse httpServletResponse = (HttpServletResponse)resp;
		
		UserStatus userStatus = new UserStatus();
		if( user!=null ){
			log.info("Welcome, logged in user " + user.getEmail());
			userStatus.setEmail(user.getEmail());
		}else{
			log.info("You better log in, dude!");
		}
		userStatus.setLoginUrl(userService.createLoginURL("/index_in.jsp"));
		userStatus.setLogoutUrl(userService.createLogoutURL("/index_out.jsp"));
		requestContexts.set( new RequestContext(httpServletRequest, httpServletResponse, userStatus));
		
		try {
			// only the request to the loginstatus is free - and in dev server also the login-page
			boolean isLoginRequest = requestURI.contains(LoginStatus.PATH_LOGINSTATUS) || requestURI.contains("/_ah") || requestURI.contains(".jsp") ;
			if (user == null && req instanceof HttpServletRequest && !isLoginRequest) {
				((HttpServletResponse)resp).sendError(503, "You are not logged in into google - first ask about the status via " 
						+ LoginStatus.PATH_LOGINSTATUS );
			} else {
				chain.doFilter(req, resp);
			}
		} finally {
			requestContexts.remove();
		}
	}
	

	/* (non-Javadoc)
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	@Override
	public void init(FilterConfig arg0) throws ServletException {
	}
	
	public static final class RequestContext{
		public final HttpServletRequest httpServletRequest;
		public final HttpServletResponse httpServletResponse;
		public final UserStatus userStatus;
		
		public RequestContext(HttpServletRequest httpServletRequest,
				HttpServletResponse httpServletResponse, UserStatus userStatus) {
			super();
			this.httpServletRequest = httpServletRequest;
			this.httpServletResponse = httpServletResponse;
			this.userStatus = userStatus;
		}
		
		public static RequestContext get(){
			return requestContexts.get();
		}
	}

}
